package org.mashart.pink.m.ws;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import org.mashart.pink.m.store.Preferences;

/**
 * The only implementation of HTTP client we have at the moment
 * @see WsConnector
 *
 * TODO make it run in a separate thread
 */
public class RestfulClient implements WsConnector {

    /**
     * <code>true</code> if this instance has been configured already
     * @see <code>configure()</code>
     */
    private boolean configured;

    /**
     * User id
     */
    private String user;

    /**
     * URL where to post GPS data to
     */
    private String wpUrl;

    /**
     * URL where to post GPS data to
     */
    private String actionUrlPrefix;
    /* TODO make it configurable from a UI */

    /**
     * HTTP connection to the server
     */
    private HttpConnection conn;

    /**
     * HTTP request data
     */
    OutputStream ostream;

    /**
     * HTTP response stream
     */
    InputStream istream;

    /**
     * Constructor. Doesn't do much of useful things */
    public RestfulClient() {
        configured = false;
        ostream = null;
        istream = null;
    }

    /**
     * Preparation for <code>initialize()</code>
     *
     * TODO I'd like to be able to configure this from a UI
     */
    public int configure() {
        Preferences pref = Preferences.getInstance();
        // get the host url from preferences
        String host = pref.get(Preferences.kUrl);
        // fault tolerant
        if ( !host.startsWith("http://") ) {
            host = "http://" + host;
        }
        if ( !host.endsWith("/") ) {
            host = host + "/";
        }
        wpUrl = host + "waypoints";
        // url prefix for sending action, ends with '/'
        actionUrlPrefix = host + "runs/";
        user = pref.get(Preferences.kUser);
        configured = true;
        return 1;
    }

    /**
     * Doesn't do anything at the moment
     */
    public int initialize() {
        if (!configured) {
            return -1;
        }else{
            return 1;
        }
    }

    /**
     * send a query string to a specified url
     */
    public int push(String aUrl, String q){
        int res = 1;
        try {

            // if the connection is lost or closed
            if(ostream == null){
            // Open HTTP connection to the specified URL
                conn = (HttpConnection) Connector.open(aUrl, Connector.WRITE, true);
                // Set the request method and headers
                conn.setRequestMethod(HttpConnection.POST);
                // Open the stream
                ostream = conn.openDataOutputStream();
            }

            ostream.write(q.getBytes());

            // DEBUG
//            System.out.print("[" + ( System.currentTimeMillis() % 1000000 ) + "]");
//            System.out.println("sending:" + q);

            ostream.flush();

             //skipResponse();
//            res = conn.getResponseCode();
//
//            /* TODO error response code handling */
//            long len = conn.getLength();
//            if (len > 0){
//                istream = conn.openInputStream();
//                istream.skip(len);
//            }
            // if require to close after use
            terminate();
            // DEBUG
//            System.out.print("[" + ( System.currentTimeMillis() % 1000000 ) + "]");
//            System.out.println("send succ:" + q);
        } catch (IOException ex) {
            // DEBUG
//            System.out.print("[" + ( System.currentTimeMillis() % 1000000 ) + "]");
//            System.out.println("send failed:" + q);
            // can't send to our web service
            res = -1;
            terminate();
            /* TODO try to reconnect instead */
        }

        return res;
    }

    /**
     * POST data in bytes to the server
     *
     * Opens HTTP connection, <code>OutputStream</code>, pushes the data
     * and closes all open streams
     */
    public int push(String s) {
        int res;
        StringBuffer msg = new StringBuffer();
        msg.append("id=").append(user).append("&").append(s);
        res = push(wpUrl, msg.toString());
        return res;
//        return push(url, s);
    }

    /**
     * Send an action String to the server
     */
    public int pushAction(String action){
        int res;
        // generate actionUrl, e.g, for "start": "http://pink.mashart.org/runs/start"
        String actionUrl = actionUrlPrefix + action;
        StringBuffer msg = new StringBuffer();
        msg.append("id=").append(user);
        res = push(actionUrl, msg.toString());
        return res;
    }

    /**
     * Closes all open stream and HTTP connection
     */
    public int terminate() {
        int res = 1;
        // Closing input stream
//        try {
//            if (istream != null) { istream.close(); }
//        } catch (IOException ex) {
//            // something went wrong
//            res = -1;
//        } finally {
//            istream = null;
//        }

        // Closing output stream
        try {
            if (ostream != null) { ostream.close(); }
        } catch (IOException ex) {
            // something went wrong
            res = -1;
        } finally {
            ostream = null;
        }

        // Closing HTTP connection
        try {
            if (conn != null) { conn.close(); }
        } catch (IOException ex) {
            // something went wrong
            res = -1;
        } finally {
            conn = null;
        }
        
        return res;
    }
}
